/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.cip.esymons.eventos.bc;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
//import java.util.Vector;
import java.util.Vector;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.cip.esymons.eventos.be.Ambiente;
import org.cip.esymons.eventos.be.Contrato;
import org.cip.esymons.eventos.be.NumeraContratos;
import org.cip.esymons.eventos.be.ReservaAmbiente;
import org.cip.esymons.eventos.be.ServicioEquipo;
import org.cip.esymons.general.be.ConsejoDepartamental;
import org.cip.esymons.general.util.Utiles;

/**
 *
 * @author oscar
 */
@Stateless
public class ContratoFacade implements ContratoFacadeLocal {

    private MontosComprobanteAdapter montos;

    @PersistenceContext
    private EntityManager em;

//    public void create(Contrato contrato) {
//        int num = 0;
//        String codNum = "";
//        Vector v = (Vector) em.createNativeQuery("select count(*)+1 from eca_contrato").getSingleResult();
//        num = (((Long) v.get(0)).intValue());
//        if (num < 10) {
//            codNum = "000000" + String.valueOf(num);
//        }
//        if (num >= 10 && num < 100) {
//            codNum = "00000" + String.valueOf(num);
//        }
//        if (num >= 100 && num < 1000) {
//            codNum = "0000" + String.valueOf(num);
//        }
//        if (num >= 1000 && num < 100000) {
//            codNum = "000" + String.valueOf(num);
//        }
//        if (num >= 10000 && num < 100000) {
//            codNum = "00" + String.valueOf(num);
//        }
//        if (num >= 100000 && num < 1000000) {
//            codNum = "0" + String.valueOf(num);
//        }
//        if (num >= 1000000 && num < 10000000) {
//            codNum = "" + String.valueOf(num);
//        }
//        contrato.setConNumero(codNum);
//        em.persist(contrato);
//    }

    //lizardo estuvo aqui
    public void create(Contrato contrato) {
        String numera = "";
        Integer numDigitos = 8;
        try {
            NumeraContratos numeracion = (NumeraContratos) em.createQuery("select n from NumeraContratos n ").getSingleResult();
            numera = numeracion.getNcoNumeracion();
            long number = Utiles.aEnteroLargo(numera) + 1;
            numera = Utiles.aCadena(number);
            numDigitos = (numeracion.getNcoNumDigitos() != null) ? numeracion.getNcoNumDigitos(): numDigitos;
            numera = Utiles.rellenarCeros(numera, numDigitos);
            numeracion.setNcoNumeracion(numera);
            em.merge(numeracion);
        } catch (Exception ex) {
            numera = "0000001";
            NumeraContratos numeracion = new NumeraContratos();
            numeracion.setNcoNumeracion(numera);
            em.persist(numeracion);
            System.out.println("FATAL: " + ex.getMessage());
        }
        contrato.setConNumero(numera);
        em.persist(contrato);
    }

    public void edit(Contrato contrato) {
        em.merge(contrato);
    }

    public void remove(Contrato contrato) {
        em.remove(em.merge(contrato));
    }

    public Contrato find(Object id) {
        return em.find(Contrato.class, id);
    }

    public List<Contrato> findAll() {
        return em.createQuery("select object(o) from Contrato as o").getResultList();
    }

    public List<Contrato> reporteFechas(Date ini, Date fin) {
        List<Contrato> lista = new ArrayList<Contrato>();
        List<ReservaAmbiente> listaReserva = new ArrayList<ReservaAmbiente>();
        List<Ambiente> listaAmbientes = new ArrayList<Ambiente>();
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        List<ServicioEquipo> listaEquipos = new ArrayList<ServicioEquipo>();
        ConsejoDepartamental cons = (ConsejoDepartamental) em.createQuery("SELECT cd FROM ConsejoDepartamental cd WHERE cd.cdeEstado = TRUE AND cd.cdeActivo = true").getSingleResult();
        lista = em.createQuery("select object(o) from Contrato as o where o.confechaContrato between ?1 and ?2").setParameter(1, ini).setParameter(2, fin).getResultList();

        for (int i = 0; i < lista.size(); i++) {
            if (lista.get(i).getConEstado() == 0) {
                lista.get(i).setEstado("Anulado");
            } else {
                if (lista.get(i).getConEstado() == 1) {
                    lista.get(i).setEstado("Sin Pagar");
                } else {
                    lista.get(i).setEstado("Pagado");
                }
            }
            lista.get(i).setConsejo(cons);
            lista.get(i).setFechaFin(sdf.format(fin));
            lista.get(i).setFechaInicio(sdf.format(ini));
            lista.get(i).setContratante(lista.get(i).getSolCodigo().getNombreDelSolicitante());
            listaReserva = em.createQuery("select object(o) from ReservaAmbiente as o where o.contrato=?1").setParameter(1, lista.get(i)).getResultList();
            for (ReservaAmbiente res : listaReserva) {
                if (res.getReaTipoae() == 0) {
                    if (!listaAmbientes.contains(res.getAmbCodigo())) {
                        listaAmbientes.add(res.getAmbCodigo());
                    }
                } else {
                    if (!listaEquipos.contains(res.getSerCodigo())) {
                        listaEquipos.add(res.getSerCodigo());
                    }
                }
            }
            lista.get(i).setRecursos("");
            for (Ambiente amb : listaAmbientes) {
                lista.get(i).setRecursos(lista.get(i).getRecursos() + "," + amb.getAmbNombre());
            }
            for (ServicioEquipo ser : listaEquipos) {
                lista.get(i).setRecursos(lista.get(i).getRecursos() + "," + ser.getSerNombre());
            }
        }
        return lista;
    }

    public List<Contrato> listarContratosxAnular() {
        return em.createQuery("select object(o) from Contrato as o where o.conEstado=1").getResultList();
    }

    //lizardo estuvo aqui
    public Contrato buscarUltimoContrato() {
        try {
            return (Contrato) em.createQuery("select con from Contrato con where con.conCodigo in (select max(c.conCodigo) from Contrato c)").getSingleResult();
        } catch (Exception ex) {
            System.out.println("FATAL: " + ex.getMessage());
            return null;
        }
    }

    public List<Contrato> listarContratos(Long solCodigo) {
        return em.createQuery("select c from Contrato c where c.solCodigo.solCodigo = ?1").setParameter(1, solCodigo).getResultList();
    }

    public Double calcularSubTotal(Contrato contrato) {
        Integer codContrato = (contrato != null) ? contrato.getConCodigo() : 0;
        List<ReservaAmbiente> lista = new ArrayList<ReservaAmbiente>();
        lista = em.createQuery("select r from ReservaAmbiente r where r.contrato.conCodigo = ?1")
                .setParameter(1, codContrato).getResultList();
        Double monto = 0D;
        for (ReservaAmbiente res : lista) {
            Double montoParcial = (res.getReamontoParcial() != null) ? res.getReamontoParcial() : 0D;
            monto += montoParcial;
        }
        return monto;
    }

    //hecho por lizardo
    private Double getMontoTotal(Integer conCodigo) {
        Double montoTotal = 0.0;
        Vector v = new Vector();
        try {
            v = (Vector) em.createNativeQuery("call sp_mostrar_monto_total (?);")
                    .setParameter(1, conCodigo)
                    .getSingleResult();
            montoTotal = (((BigDecimal) v.get(0)).doubleValue());
            return montoTotal;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    private Double getIgvVigente() {
        Double igv = 0.0;
        Vector v = new Vector();
        try {
            v = (Vector) em.createNativeQuery("call sp_mostrar_igv_vigente ();")
                    .getSingleResult();
            igv = (((Double) v.get(0)).doubleValue());
            return igv;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    private Double getDescuento(Integer conCodigo) {
        Double descuento = 0.0;
        Vector v = new Vector();
        try {
            v = (Vector) em.createNativeQuery("call sp_mostrar_descuento (?);")
                    .setParameter(1, conCodigo)
                    .getSingleResult();
            descuento = ((Double) v.get(0)).doubleValue();
            return descuento;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    private String getHorario(Integer conCodigo, Integer ambServicio, Integer tipo, Date fecha) {
        String horario = "";
        try {
            Query q = em.createNativeQuery("call sp_mostrar_horarios (?,?,?,?);")
                    .setParameter(1, conCodigo)
                    .setParameter(2, ambServicio)
                    .setParameter(3, tipo)
                    .setParameter(4, fecha);
            List lista = q.getResultList();
            if (lista.size() > 0) {
                for (Iterator i = lista.iterator(); i.hasNext();) {
                    Vector v = (Vector) i.next();   //0=rea_horaInicio, 1=rea_horaFin
                    Double horaInicio = ((Double) v.get(0)).doubleValue();
                    Double horaFin = ((Double) v.get(1)).doubleValue();
                    int intHoraInicio = horaInicio.intValue();
                    int intHoraFin = horaFin.intValue();
                    String strHourBegin = Utiles.aCadena(intHoraInicio);
                    String strHourEnd = Utiles.aCadena(intHoraFin);
                    String strInicio = Utiles.rellenarCeros(strHourBegin, 2);
                    String strFin = Utiles.rellenarCeros(strHourEnd, 2);
                    horario += strInicio + ":00" + " - " + strFin + ":00 ";
                }
            }
            return horario;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    private Boolean verificarValores(Double montoTotal, Double igv) {
        if (montoTotal != null) {
            if (igv != null) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public List<ComprobanteAdapter> getListaComprobante(Integer conCodigo, Double igv, Double factorTotal) {
        List<ComprobanteAdapter> listaComprobante = new ArrayList<ComprobanteAdapter>();
        Double subTotal = 0.0;
        try {
            Query q = em.createNativeQuery("call sp_listar_comprobante (?);")
                    .setParameter(1, conCodigo);
            List lista = q.getResultList();
            if (lista.size() > 0) {
                Integer indice = 0;
                Integer tamanio = lista.size();
                for (Iterator i = lista.iterator(); i.hasNext();) {
                    indice++;
                    Vector v = (Vector) i.next();   //0=amb_ser, 1=fecha, 2=cantidad, 3=costo, 4=tipo
                    Integer ambServicio = ((Long) v.get(0)).intValue();
                    Date fecha = ((Date) v.get(1));
                    Integer cantidad = ((Long) v.get(2)).intValue();
                    Double costo = ((Double) v.get(3)).doubleValue();
                    costo = costo / (1 + (igv / 100));
                    costo = Utiles.redondearDouble(costo, 2);
                    Double importe = cantidad * costo;
                    importe = Utiles.truncarDouble(importe, 2);
                    if (indice == tamanio) {
                        importe = factorTotal - subTotal;
                        costo = importe / cantidad;
                        costo = Utiles.truncarDouble(costo, 3);
                    } else {
                        subTotal += importe;
                    }
                    Integer tipo = ((Integer) v.get(4)).intValue();
                    ComprobanteAdapter com = new ComprobanteAdapter(indice,ambServicio,fecha,cantidad,costo,tipo);
                    String descripcion = null;
                    String horario = getHorario(conCodigo, ambServicio, tipo, fecha);
                    if (tipo == 0) {
                        Query q1 = em.createNativeQuery("call sp_mostrar_nombre_ambiente (?);")
                                .setParameter(1, ambServicio);
                        List lista1 = q1.getResultList();
                        if (lista1.size() > 0) {
                            for (Iterator j = lista1.iterator(); j.hasNext();) {
                                Vector v1 = (Vector) j.next();
                                descripcion = ((String) v1.get(0)).toString();
                                break;
                            }
                        }
                    } else {
                        Query q1 = em.createNativeQuery("call sp_mostrar_nombre_servicio (?);")
                                .setParameter(1, ambServicio);
                        List lista1 = q1.getResultList();
                        if (lista1.size() > 0) {
                            for (Iterator j = lista1.iterator(); j.hasNext();) {
                                Vector v1 = (Vector) j.next();
                                descripcion = ((String) v1.get(0)).toString();
                                break;
                            }
                        }
                    }
                    com.setDescripcion(descripcion);
                    com.setHorario(horario);
                    com.setImporte(importe);
                    listaComprobante.add(com);
                }
            }
            return listaComprobante;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    public List<ComprobanteAdapter> getListaComprobante(List<ComprobanteAdapter> listaComprobante, List<FactorAdapter> listaFactores, Double factorToral) {
        try {
            //Integer ambServicio = null;
            Integer indice = 0;
            Double valor = 0.0;
            Double subTotal = 0.0;
            int tamanio = 0;
            int i = 0;
            List<FactorAdapter> listaFac = new ArrayList<FactorAdapter>();
            if (listaFactores.size() > 0) {
                tamanio = listaFactores.size();
                for (ComprobanteAdapter com : listaComprobante) {
                    i++;
                    listaFac = listaFactores;
                    for (FactorAdapter factor : listaFac) {
                        //ambServicio = factor.getAmbServicio();
                        indice = factor.getIndice();
                        //if (com.getAmbServicio() == ambServicio) {
                        if (com.getIndice() == indice) {
                            valor = factor.getValor();
                            break;
                        }
                    }
                    Double importe = (valor * factorToral) / 100;
                    importe = Utiles.redondearDouble(importe, 2);
                    if (i == tamanio) {
                        importe = factorToral - subTotal;
                    } else {
                        subTotal += importe;
                    }
                    Integer cantidad = com.getCantidad();
                    Double costo = importe / cantidad;
                    costo = Utiles.redondearDouble(costo, 3);
                    com.setCosto(costo);
                    com.setImporte(importe);
                }
            }
            listaFac = null;
            return listaComprobante;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    public List<FactorAdapter> getListaFactores(Integer conCodigo, Double igv, Double factorTotal) {
        List<FactorAdapter> listaFactores = new ArrayList<FactorAdapter>();
        try {
            Query q = em.createNativeQuery("call sp_listar_comprobante (?);")
                    .setParameter(1, conCodigo);
            List lista = q.getResultList();
            if (lista.size() > 0) {
                Integer indice = 0;
                for (Iterator i = lista.iterator(); i.hasNext();) {
                    indice++;
                    Vector v = (Vector) i.next();   //0=amb_ser, 1=fecha, 2=cantidad, 3=costo, 4=tipo
                    Integer ambServicio = ((Long) v.get(0)).intValue();
                    Integer cantidad = ((Long) v.get(2)).intValue();
                    Double costo = ((Double) v.get(3)).doubleValue();
                    costo = costo / (1 + (igv / 100));
                    costo = Utiles.redondearDouble(costo,2);
                    Double importe = cantidad * costo;
                    importe = Utiles.truncarDouble(importe, 2);
                    Double valor = (importe * 100) / factorTotal;
                    valor = Utiles.redondearDouble(valor, 2);
                    FactorAdapter factor = new FactorAdapter(indice, ambServicio, valor);
                    listaFactores.add(factor);
                }
            }
            return listaFactores;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return null;
        }
    }

    public List<ComprobanteAdapter> recalcularComprobante(Integer conCodigo, Double descuento) {
        Double montoTotal = getMontoTotal(conCodigo);
        Double igvVigente = getIgvVigente();
        //Double descuento = getDescuento(conCodigo);
        descuento = (descuento != null) ? descuento : 0.0;
        Double subTotal;
        Double igv;
        Double factorTotal;
        List<FactorAdapter> listaFactores = new ArrayList<FactorAdapter>();
        List<ComprobanteAdapter> listaComprobantes = new ArrayList<ComprobanteAdapter>();
        if (verificarValores(montoTotal, igvVigente)) {
            subTotal = montoTotal / (1+(igvVigente / 100));
            subTotal = Utiles.redondearDouble(subTotal, 2);
            igv = montoTotal - subTotal;
            igv = Utiles.truncarDouble(igv, 2);
            factorTotal = subTotal;
            listaComprobantes = getListaComprobante(conCodigo, igvVigente, factorTotal);
            if (descuento > 0.0) {
                listaFactores = getListaFactores(conCodigo, igvVigente, factorTotal);
                montoTotal = montoTotal - descuento;
                subTotal = montoTotal / (1+(igvVigente / 100));
                subTotal = Utiles.redondearDouble(subTotal, 2);
                igv = montoTotal - subTotal;
                igv = Utiles.redondearDouble(igv, 2);
                listaComprobantes = getListaComprobante(listaComprobantes, listaFactores, subTotal);
            }
        } else {
            return null;
        }
        montos = new MontosComprobanteAdapter(subTotal, igv, montoTotal,descuento);
        return listaComprobantes;
    }

    public MontosComprobanteAdapter getMontosComprobante() {
        return this.montos;
    }

    public Boolean anularMovimientoCuenta(Integer conCodigo) {
        Integer resultado = null;
        Vector v = new Vector();
        try {
            v = (Vector) em.createNativeQuery("call sp_anular_movimientos_cuenta (?);")
                    .setParameter(1, conCodigo)
                    .getSingleResult();
            resultado = (((Long) v.get(0)).intValue());
            return (resultado == 1) ? true : false;
        } catch (Exception e) {
            System.out.println("FATAL: " + e.getMessage());
            return false;
        }
    }

}
